From 7c27ac1d0738a541e4fdc57c09446f6694445254 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Mon, 26 Sep 2005 22:09:07 +0000 Subject: [PATCH] update due to information from BablFishStats --- ChangeLog | 23 ++++ babl/base/model-gray.c | 103 ++++++++++++-- babl/base/model-rgb.c | 241 +++++++++++++++++++++++++-------- babl/base/model-ycbcr.c | 12 +- docs/index-static.html.in | 4 +- extensions/gggl.c | 273 ++++++++++++++++++++++++-------------- 6 files changed, 484 insertions(+), 172 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8385846..4bc74d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-09-27 Øyvind Kolås + + Updates done due to improvements gotten from BablFishStat feedback. + + * babl/base/model-gray.c: (components), (models), + (rgba2gray_gamma_2_2_premultiplied), + (gray_gamma_2_2_premultiplied2rgba), (conversions): + * babl/base/model-rgb.c: (components), (models), (copy_strip_1), + (g3_gamma_2_2), (g3_inv_gamma_2_2), + (non_premultiplied_to_premultiplied), + (premultiplied_to_non_premultiplied), + (rgba2rgba_gamma_2_2_premultiplied), + (rgba_gamma_2_2_premultiplied2rgba), (rgba2rgba_gamma_2_2), + (rgba_gamma_2_22rgba), (conversions), (formats): + * babl/base/model-ycbcr.c: (models), (formats): + * docs/index-static.html.in: + * extensions/gggl.c: (conv_F_8), (conv_8_F), (conv_F_D), + (conv_D_F), (conv_rgba8_rgbaF), (conv_rgb8_rgbF), (conv_ga8_gaF), + (conv_rgbaF_rgbaD), (conv_rgbaD_rgbaF), (conv_rgbAF_rgbaF), + (conv_rgbaF_rgbAF), (conv_rgbaF_rgbF), (conv_rgbF_rgbaF), + (conv_rgbaF_gaF), (conv_rgbaF_rgb8), (conv_rgbA16_rgbaF), + (conv_rgb8_rgba8), (conv_rgbA8_rgb8), (init): + 2005-09-27 Øyvind Kolås Upgrade of BablFishPath. diff --git a/babl/base/model-gray.c b/babl/base/model-gray.c index 37044cf..e96a029 100644 --- a/babl/base/model-gray.c +++ b/babl/base/model-gray.c @@ -53,7 +53,13 @@ components (void) babl_component_new ( "Y'", - "id", BABL_LUMINANCE_GAMMA_2_2, + "id", BABL_LUMA, + "luma", + NULL); + + babl_component_new ( + "Y'a", + "id", BABL_LUMA_MUL_ALPHA, "luma", NULL); } @@ -66,26 +72,34 @@ models (void) babl_component_id (BABL_LUMINANCE), NULL); + babl_model_new ( - "id", BABL_GRAY_GAMMA_2_2, - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + "id", BABL_GRAY_ALPHA, + babl_component_id (BABL_LUMINANCE), + babl_component_id (BABL_ALPHA), NULL); babl_model_new ( - "id", BABL_GRAY_GAMMA_2_2_ALPHA, - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + "id", BABL_GRAY_ALPHA_PREMULTIPLIED, + babl_component_id (BABL_LUMINANCE_MUL_ALPHA), babl_component_id (BABL_ALPHA), NULL); + babl_model_new ( - "id", BABL_GRAY_ALPHA, - babl_component_id (BABL_LUMINANCE), + "id", BABL_GRAY_GAMMA_2_2, + babl_component_id (BABL_LUMA), + NULL); + + babl_model_new ( + "id", BABL_GRAY_GAMMA_2_2_ALPHA, + babl_component_id (BABL_LUMA), babl_component_id (BABL_ALPHA), NULL); babl_model_new ( - "id", BABL_GRAY_ALPHA_PREMULTIPLIED, - babl_component_id (BABL_LUMINANCE_MUL_ALPHA), + "id", BABL_GRAY_GAMMA_2_2_ALPHA_PREMULTIPLIED, + babl_component_id (BABL_LUMA_MUL_ALPHA), babl_component_id (BABL_ALPHA), NULL); } @@ -412,6 +426,62 @@ premultiplied_to_non_premultiplied (int src_bands, return n; } +static long +rgba2gray_gamma_2_2_premultiplied (void *src, + void *dst, + long n) +{ + while (n--) + { + double red = ((double*)src)[0]; + double green = ((double*)src)[1]; + double blue = ((double*)src)[2]; + double alpha = ((double*)src)[3]; + + double luminance; + double luma; + + luminance = red * RGB_LUMINANCE_RED + + green * RGB_LUMINANCE_GREEN + + blue * RGB_LUMINANCE_BLUE; + luma = linear_to_gamma_2_2 (luminance); + + ((double*)dst)[0] = luma * alpha; + ((double*)dst)[1] = alpha; + + src+=4 * sizeof (double); + dst+=2 * sizeof (double); + } + return n; +} + + +static long +gray_gamma_2_2_premultiplied2rgba (void *src, + void *dst, + long n) +{ + while (n--) + { + double luma = ((double*) src)[0]; + double alpha = ((double*) src)[1]; + double luminance; + + luma = luma / alpha; + luminance = gamma_2_2_to_linear (luma); + + ((double*)dst)[0] = luminance; + ((double*)dst)[1] = luminance; + ((double*)dst)[2] = luminance; + ((double*)dst)[3] = alpha; + + src+=2 * sizeof (double); + dst+=4 * sizeof (double); + } + return n; +} + + static void conversions (void) { @@ -443,6 +513,21 @@ conversions (void) NULL ); + + babl_conversion_new ( + babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA_PREMULTIPLIED), + babl_model_id (BABL_RGBA), + "linear", gray_gamma_2_2_premultiplied2rgba, + NULL + ); + + babl_conversion_new ( + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA_PREMULTIPLIED), + "linear", rgba2gray_gamma_2_2_premultiplied, + NULL + ); + babl_conversion_new ( babl_model_id (BABL_GRAY), babl_model_id (BABL_RGBA), diff --git a/babl/base/model-rgb.c b/babl/base/model-rgb.c index e64a86f..0cb7e3f 100644 --- a/babl/base/model-rgb.c +++ b/babl/base/model-rgb.c @@ -40,6 +40,30 @@ static void components (void) { + + + babl_component_new ( + "Ra", + "id", BABL_RED_MUL_ALPHA, + "luma", + "chroma", + "alpha", + NULL); + babl_component_new ( + "Ga", + "id", BABL_GREEN_MUL_ALPHA, + "luma", + "chroma", + "alpha", + NULL); + babl_component_new ( + "Ba", + "id", BABL_BLUE_MUL_ALPHA, + "luma", + "chroma", + "alpha", + NULL); + babl_component_new ( "R'", "id", BABL_RED_GAMMA_2_2, @@ -61,29 +85,26 @@ components (void) "chroma", NULL); - babl_component_new ( - "Ra", - "id", BABL_RED_MUL_ALPHA, + "R'a", + "id", BABL_RED_GAMMA_2_2_MUL_ALPHA, "luma", "chroma", - "alpha", NULL); + babl_component_new ( - "Ga", - "id", BABL_GREEN_MUL_ALPHA, - "luma", - "chroma", - "alpha", - NULL); + "G'a", + "id", BABL_GREEN_GAMMA_2_2_MUL_ALPHA, + "luma", + "chroma", + NULL); + babl_component_new ( - "Ba", - "id", BABL_BLUE_MUL_ALPHA, - "luma", - "chroma", - "alpha", - NULL); - + "B'a", + "id", BABL_BLUE_GAMMA_2_2_MUL_ALPHA, + "luma", + "chroma", + NULL); } static void @@ -119,6 +140,14 @@ models (void) babl_component_id (BABL_BLUE_GAMMA_2_2), babl_component_id (BABL_ALPHA), NULL); + + babl_model_new ( + "id", BABL_RGBA_GAMMA_2_2_PREMULTIPLIED, + babl_component_id (BABL_RED_GAMMA_2_2_MUL_ALPHA), + babl_component_id (BABL_GREEN_GAMMA_2_2_MUL_ALPHA), + babl_component_id (BABL_BLUE_GAMMA_2_2_MUL_ALPHA), + babl_component_id (BABL_ALPHA), + NULL); } static long @@ -128,8 +157,9 @@ copy_strip_1 (int src_bands, int dst_bands, void **dst, int *dst_pitch, - long n) + long samples) { + long n=samples; BABL_PLANAR_SANITY while (n--) { @@ -147,7 +177,7 @@ copy_strip_1 (int src_bands, BABL_PLANAR_STEP } - return n; + return samples; } static long @@ -157,10 +187,10 @@ g3_gamma_2_2 (int src_bands, int dst_bands, void **dst, int *dst_pitch, - long n) + long samples) { + long n=samples; BABL_PLANAR_SANITY - while (n--) { int band; @@ -171,7 +201,7 @@ g3_gamma_2_2 (int src_bands, BABL_PLANAR_STEP } - return n; + return samples; } @@ -182,10 +212,10 @@ g3_inv_gamma_2_2 (int src_bands, int dst_bands, void **dst, int *dst_pitch, - long n) + long samples) { + long n=samples; BABL_PLANAR_SANITY - while (n--) { int band; @@ -202,7 +232,7 @@ g3_inv_gamma_2_2 (int src_bands, } BABL_PLANAR_STEP } - return n; + return samples; } static long @@ -212,10 +242,10 @@ non_premultiplied_to_premultiplied (int src_bands, int dst_bands, void **dst, int *dst_pitch, - long n) + long samples) { + long n=samples; BABL_PLANAR_SANITY - while (n--) { double alpha; @@ -230,7 +260,7 @@ non_premultiplied_to_premultiplied (int src_bands, BABL_PLANAR_STEP } - return n; + return samples; } static long @@ -240,10 +270,10 @@ premultiplied_to_non_premultiplied (int src_bands, int dst_bands, void **dst, int *dst_pitch, - long n) + long samples) { + long n=samples; BABL_PLANAR_SANITY - while (n--) { double alpha; @@ -265,7 +295,91 @@ premultiplied_to_non_premultiplied (int src_bands, BABL_PLANAR_STEP } - return n; + return samples; +} + + + +static long +rgba2rgba_gamma_2_2_premultiplied (void *src, + void *dst, + long samples) +{ + long n=samples; + while (n--) + { + double alpha = ((double*)src)[3]; + ((double*)dst)[0] = linear_to_gamma_2_2 (((double*) src)[0]) * alpha; + ((double*)dst)[1] = linear_to_gamma_2_2 (((double*) src)[1]) * alpha; + ((double*)dst)[2] = linear_to_gamma_2_2 (((double*) src)[2]) * alpha; + ((double*)dst)[3] = alpha; + src+=4 * sizeof (double); + dst+=4 * sizeof (double); + } + return samples; +} + + +static long +rgba_gamma_2_2_premultiplied2rgba (void *src, + void *dst, + long samples) +{ + long n=samples; + while (n--) + { + double alpha = ((double*) src)[3]; + ((double*)dst)[0] = gamma_2_2_to_linear (((double*) src)[0] / alpha); + ((double*)dst)[1] = gamma_2_2_to_linear (((double*) src)[1] / alpha); + ((double*)dst)[2] = gamma_2_2_to_linear (((double*) src)[2] / alpha); + ((double*)dst)[3] = alpha; + + src+=4 * sizeof (double); + dst+=4 * sizeof (double); + } + return samples; +} + + +static long +rgba2rgba_gamma_2_2 (void *src, + void *dst, + long samples) +{ + long n=samples; + while (n--) + { + double alpha = ((double*)src)[3]; + ((double*)dst)[0] = linear_to_gamma_2_2 (((double*) src)[0]); + ((double*)dst)[1] = linear_to_gamma_2_2 (((double*) src)[1]); + ((double*)dst)[2] = linear_to_gamma_2_2 (((double*) src)[2]); + ((double*)dst)[3] = alpha; + src+=4 * sizeof (double); + dst+=4 * sizeof (double); + } + return samples; +} + + +static long +rgba_gamma_2_22rgba (void *src, + void *dst, + long samples) +{ + long n=samples; + + while (n--) + { + double alpha = ((double*) src)[3]; + ((double*)dst)[0] = gamma_2_2_to_linear (((double*) src)[0]); + ((double*)dst)[1] = gamma_2_2_to_linear (((double*) src)[1]); + ((double*)dst)[2] = gamma_2_2_to_linear (((double*) src)[2]); + ((double*)dst)[3] = alpha; + + src+=4 * sizeof (double); + dst+=4 * sizeof (double); + } + return samples; } static void @@ -278,68 +392,77 @@ conversions (void) NULL ); + babl_conversion_new ( + babl_model_id (BABL_RGB), babl_model_id (BABL_RGBA), - babl_model_id (BABL_RGB_GAMMA_2_2), - "planar", g3_gamma_2_2, + "planar", copy_strip_1, NULL ); babl_conversion_new ( babl_model_id (BABL_RGBA), - babl_model_id (BABL_RGBA_GAMMA_2_2), - "planar", g3_gamma_2_2, + babl_model_id (BABL_RGB), + "planar", copy_strip_1, NULL ); babl_conversion_new ( - babl_model_id (BABL_RGB_GAMMA_2_2), babl_model_id (BABL_RGBA), - "planar", g3_inv_gamma_2_2, + babl_model_id (BABL_RGBA_PREMULTIPLIED), + "planar", non_premultiplied_to_premultiplied, NULL ); babl_conversion_new ( - babl_model_id (BABL_RGBA_GAMMA_2_2), + babl_model_id (BABL_RGBA_PREMULTIPLIED), babl_model_id (BABL_RGBA), - "planar", g3_inv_gamma_2_2, + "planar", premultiplied_to_non_premultiplied, NULL ); babl_conversion_new ( - babl_model_id (BABL_RGB), babl_model_id (BABL_RGBA), - "planar", copy_strip_1, + babl_model_id (BABL_RGB_GAMMA_2_2), + "planar", g3_gamma_2_2, NULL ); - babl_conversion_new ( + babl_model_id (BABL_RGB_GAMMA_2_2), babl_model_id (BABL_RGBA), - babl_model_id (BABL_RGB), - "planar", copy_strip_1, + "planar", g3_inv_gamma_2_2, NULL ); babl_conversion_new ( babl_model_id (BABL_RGBA), - babl_model_id (BABL_RGBA_PREMULTIPLIED), - "planar", non_premultiplied_to_premultiplied, - NULL - ); + babl_model_id (BABL_RGBA_GAMMA_2_2), + "linear", rgba2rgba_gamma_2_2, + NULL); + babl_conversion_new ( + babl_model_id (BABL_RGBA_GAMMA_2_2), + babl_model_id (BABL_RGBA), + "linear", rgba_gamma_2_22rgba, + NULL); babl_conversion_new ( - babl_model_id (BABL_RGBA_PREMULTIPLIED), babl_model_id (BABL_RGBA), - "planar", premultiplied_to_non_premultiplied, - NULL - ); + babl_model_id (BABL_RGBA_GAMMA_2_2_PREMULTIPLIED), + "linear", rgba2rgba_gamma_2_2_premultiplied, + NULL); + babl_conversion_new ( + babl_model_id (BABL_RGBA_GAMMA_2_2_PREMULTIPLIED), + babl_model_id (BABL_RGBA), + "linear", rgba_gamma_2_2_premultiplied2rgba, + NULL); + } static void formats (void) { babl_format_new ( - "name", "srgb", + //"name", "srgb", "id", BABL_SRGB, babl_model_id (BABL_RGB_GAMMA_2_2), babl_type_id (BABL_U8), @@ -376,4 +499,16 @@ formats (void) babl_component_id (BABL_GREEN), babl_component_id (BABL_BLUE), NULL); + +#ifdef XXXX + babl_format_new ( + "id", BABL_RGB565, + babl_model_id (BABL_RGB), + babl_component_id (BABL_RED), + babl_component_id (BABL_GREEN), + babl_component_id (BABL_BLUE), + + ); +#endif } + diff --git a/babl/base/model-ycbcr.c b/babl/base/model-ycbcr.c index 000f32d..b27c5d3 100644 --- a/babl/base/model-ycbcr.c +++ b/babl/base/model-ycbcr.c @@ -60,14 +60,14 @@ models (void) { babl_model_new ( "id", BABL_YCBCR, - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_component_id (BABL_CB), babl_component_id (BABL_CR), NULL); babl_model_new ( "id", BABL_YCBCR_ALPHA, - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_component_id (BABL_CB), babl_component_id (BABL_CR), babl_component_id (BABL_ALPHA), @@ -244,7 +244,7 @@ formats (void) babl_model_id (BABL_YCBCR), babl_type_id (BABL_U8_LUMA), babl_sampling (1, 1), - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_type_id (BABL_U8_CHROMA), babl_sampling (2, 2), babl_component_id (BABL_CB), @@ -260,7 +260,7 @@ formats (void) babl_model_id (BABL_YCBCR), babl_type_id (BABL_U8_LUMA), babl_sampling (1, 1), - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_type_id (BABL_U8_CHROMA), babl_sampling (2, 2), babl_component_id (BABL_CB), @@ -276,7 +276,7 @@ formats (void) babl_model_id (BABL_YCBCR), babl_type_id (BABL_U8_LUMA), babl_sampling (1, 1), - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_type_id (BABL_U8_CHROMA), babl_sampling (2, 1), babl_component_id (BABL_CB), @@ -291,7 +291,7 @@ formats (void) babl_model_id (BABL_YCBCR), babl_type_id (BABL_U8_LUMA), babl_sampling (1, 1), - babl_component_id (BABL_LUMINANCE_GAMMA_2_2), + babl_component_id (BABL_LUMA), babl_type_id (BABL_U8_CHROMA), babl_sampling (4, 1), babl_component_id (BABL_CB), diff --git a/docs/index-static.html.in b/docs/index-static.html.in index 0f243af..d0ec866 100644 --- a/docs/index-static.html.in +++ b/docs/index-static.html.in @@ -192,9 +192,7 @@

Shortcut coverage

-

The diagram shown below is the coverage of shortcut conversions that already exist, - prior to the BablFishPath actually being operational, due to lack of testing of loss - against the reference conversions this is the most optimistic estimate. (Interactive version) +

The diagram shown below is the coverage of shortcut conversions that already exist, only chains of converions that produce the same results as the reference conversions would result in are shown.

 
diff --git a/extensions/gggl.c b/extensions/gggl.c
index 070d4cc..b5dc30d 100644
--- a/extensions/gggl.c
+++ b/extensions/gggl.c
@@ -49,7 +49,7 @@
  *       gamma correction  (not really,. gamma correction belongs in seperate ops,.
  */
 
-#define USE_TABLES
+//#define USE_TABLES
 #ifdef USE_TABLES
 
 /* lookup tables used in conversion */
@@ -147,7 +147,6 @@ gggl_float_to_index16 (float f)
   return u.s[1];
 }
 
-
 static INLINE long
 conv_F_8 (unsigned char *src, unsigned char *dst, long samples)
 {
@@ -218,19 +217,13 @@ conv_F_8 (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      float     f = ((*(float *) src));
-      if (f < 0.0)
-        {
-          *(unsigned char *) dst = 0;
-        }
-      else if (f > 1.0)
-        {
-          *(unsigned char *) dst = 255;
-        }
-      else
-        {
-          *(unsigned char *) dst = rint (f * 255.0);
-        }
+      float f  = ((*(float *) src));
+      int   uval = rint (f * 255.0);
+
+      if (uval < 0) uval = 0;
+      if (uval > 255) uval = 255;
+      *(unsigned char *) dst = uval;
+
       dst += 1;
       src += 4;
     }
@@ -268,7 +261,7 @@ conv_8_F (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      (*(float *) dst) = (*(unsigned char *) src / 255.0);
+      (*(float *) dst) = ((*(unsigned char *) src) / 255.0);
       dst += 4;
       src += 1;
     }
@@ -291,6 +284,33 @@ conv_16_F (unsigned char *src, unsigned char *dst, long samples)
 
 #endif
 
+
+static INLINE long
+conv_F_D (unsigned char *src, unsigned char *dst, long samples)
+{
+  long n=samples;
+  while (n--)
+    {
+      *(double *) dst = ((*(float *) src));
+      dst += 8;
+      src += 4;
+    }
+  return samples;
+}
+
+static INLINE long
+conv_D_F (unsigned char *src, unsigned char *dst, long samples)
+{
+  long n=samples;
+  while (n--)
+    {
+      *(float *) dst = ((*(double *) src));
+      dst += 4;
+      src += 8;
+    }
+  return samples;
+}
+
 static INLINE long
 conv_16_8 (unsigned char *src, unsigned char *dst, long samples)
 {
@@ -373,28 +393,39 @@ conv_gaF_ga16 (unsigned char *src, unsigned char *dst, long samples)
 static INLINE long
 conv_rgba8_rgbaF (unsigned char *src, unsigned char *dst, long samples)
 {
-  conv_8_F (src, dst, samples * 4);
-  return samples;
+  return conv_8_F (src, dst, samples * 4) / 4;
 }
 
 static INLINE long
 conv_rgb8_rgbF (unsigned char *src, unsigned char *dst, long samples)
 {
-  conv_8_F (src, dst, samples * 3);
-  return samples;
+  return conv_8_F (src, dst, samples * 3) / 3;
 }
 
 static INLINE long
 conv_ga8_gaF (unsigned char *src, unsigned char *dst, long samples)
 {
-  conv_8_F (src, dst, samples * 2);
-  return samples;
+  return conv_8_F (src, dst, samples * 2) / 2;
 }
 
 #define conv_rgbA8_rgbAF conv_rgba8_rgbaF
 #define conv_gA8_gAF     conv_ga8_gaF
 #define conv_g8_gF       conv_8_F
 
+static INLINE long
+conv_rgbaF_rgbaD (unsigned char *src, unsigned char *dst, long samples)
+{
+  conv_F_D (src, dst, samples * 4);
+  return samples;
+}
+
+static INLINE long
+conv_rgbaD_rgbaF (unsigned char *src, unsigned char *dst, long samples)
+{
+  conv_D_F (src, dst, samples * 4);
+  return samples;
+}
+
 static INLINE long
 conv_rgba16_rgbaF (unsigned char *src, unsigned char *dst, long samples)
 {
@@ -514,7 +545,7 @@ conv_rgbAF_rgbaF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      float     alpha = (*(float *) (src + 4 * 3));
+      float     alpha = (((float *) src)[3]);
       int       c;
       if (alpha >= 1.0)
         {
@@ -556,7 +587,7 @@ conv_rgbaF_rgbAF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      float     alpha = (*(float *) (src + 4 * 3));
+      float     alpha = (((float *) src)[3]);
       int       c;
 
       if (alpha >= 1.0)
@@ -601,13 +632,13 @@ conv_rgbaF_rgbF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      *(int *) dst = (*(int *) src);
+      *(float *) dst = (*(float *) src);
       dst += 4;
       src += 4;
-      *(int *) dst = (*(int *) src);
+      *(float *) dst = (*(float *) src);
       dst += 4;
       src += 4;
-      *(int *) dst = (*(int *) src);
+      *(float *) dst = (*(float *) src);
       dst += 4;
       src += 4;
       src += 4;
@@ -621,15 +652,15 @@ conv_rgbF_rgbaF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      *(int *) dst = (*(int *) src);
-      dst += 4;
+      *(float *) dst = (*(float *) src);
       src += 4;
-      *(int *) dst = (*(int *) src);
       dst += 4;
+      *(float *) dst = (*(float *) src);
       src += 4;
-      *(int *) dst = (*(int *) src);
       dst += 4;
+      *(float *) dst = (*(float *) src);
       src += 4;
+      dst += 4;
       *(float *) dst = 1.0;
       dst += 4;
     }
@@ -739,15 +770,15 @@ conv_rgbaF_gaF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      int       c;
-      float     sum = 0;
+      float     gray = 0;
 
-      for (c = 0; c < 3; c++)
-        {
-          sum += (*(float *) src);
-          src += 4;
-        }
-      (*(float *) dst) = sum / 3;
+      gray += (*(float *) src) * 0.212671;
+      src += 4;
+      gray += (*(float *) src) * 0.715160;
+      src += 4;
+      gray += (*(float *) src) * 0.072169;
+      src += 4;
+      (*(float *) dst) = gray;
       dst += 4;
       (*(int *) dst) = (*(int *) src);
       dst += 4;
@@ -838,7 +869,7 @@ conv_rgbaF_rgb8 (unsigned char *src, unsigned char *dst, long samples)
 
       for (c = 0; c < 3; c++)
         {
-          *(unsigned char *) dst = (*(float *) src) * 255.0;
+          *(unsigned char *) dst = rint ((*(float *) src) * 255.0);
           dst += 1;
           src += 4;
         }
@@ -914,7 +945,7 @@ conv_rgbA16_rgbaF (unsigned char *src, unsigned char *dst, long samples)
   long n=samples;
   while (n--)
     {
-      float     alpha = (*(unsigned short *) src + (3)) / 65535.0;
+      float     alpha = (((unsigned short *) src)[3]) / 65535.0;
       int       c;
 
       for (c = 0; c < 3; c++)
@@ -1242,15 +1273,16 @@ conv_rgb8_rgba8 (unsigned char *src, unsigned char *dst, long samples)
   long n=samples; 
   while (n--)
     {
-      *(unsigned int *) dst = *(unsigned int *) src;
+      /**(unsigned int *) dst = *(unsigned int *) src;
+      dst[3] = 255;*/
+
+      dst[0] = src[0];
+      dst[1] = src[1];
+      dst[2] = src[2];
       dst[3] = 255;
       src += 3;
       dst += 4;
     }
-  dst[0] = src[0];
-  dst[1] = src[1];
-  dst[2] = src[2];
-  dst[3] = 255;
   return samples;
 }
 
@@ -1311,7 +1343,36 @@ conv_rgba8_rgb8 (unsigned char *src, unsigned char *dst, long samples)
   return samples;
 }
 
-#define conv_rgbA8_rgb8 conv_rgbP8_rgb8
+static INLINE long
+conv_rgbA8_rgb8 (unsigned char *src, unsigned char *dst, long samples)
+{
+  long n=samples;
+  while (n--)
+    {
+      int alpha = src[3];
+      if (alpha == 255)
+        {
+          *dst++ = src[0];
+          *dst++ = src[1];
+          *dst++ = src[2];
+        }
+      else if (alpha == 0)
+        {
+          *dst++ = 0;
+          *dst++ = 0;
+          *dst++ = 0;
+        }
+      else
+        {
+          unsigned int aa = (255 << 16) / alpha;
+          *dst++ = (src[0] * aa) >> 16;
+          *dst++ = (src[1] * aa) >> 16;
+          *dst++ = (src[2] * aa) >> 16;
+        }
+      src += 4;
+    }
+  return samples;
+}
 
 #ifndef byteclamp
 #define byteclamp(j) do{if(j<0)j=0; else if(j>255)j=255;}while(0)
@@ -1689,125 +1750,133 @@ typedef struct Conversion
 int
 init (void)
 {
+  Babl *rgbaD = babl_format_new (
+      babl_model ("R'G'B'A"),
+      babl_type  ("double"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
+      babl_component ("A"),
+      NULL);
   Babl *rgbaF = babl_format_new (
-      babl_model ("RGBA"),
+      babl_model ("R'G'B'A"),
       babl_type  ("float"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       babl_component ("A"),
       NULL);
   Babl *rgba16 = babl_format_new (
-      babl_model ("RGBA"),
+      babl_model ("R'G'B'A"),
       babl_type  ("u16"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       babl_component ("A"),
       NULL);
   Babl *rgba8 = babl_format_new (
-      babl_model ("RGBA"),
+      babl_model ("R'G'B'A"),
       babl_type  ("u8"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       babl_component ("A"),
       NULL);
   Babl *rgbAF = babl_format_new (
-      babl_model ("RaGaBaA"),
+      babl_model ("R'aG'aB'aA"),
       babl_type  ("float"),
-      babl_component ("Ra"),
-      babl_component ("Ga"),
-      babl_component ("Ba"),
+      babl_component ("R'a"),
+      babl_component ("G'a"),
+      babl_component ("B'a"),
       babl_component ("A"),
       NULL);
   Babl *rgbA16 = babl_format_new (
-      babl_model ("RaGaBaA"),
+      babl_model ("R'aG'aB'aA"),
       babl_type  ("u16"),
-      babl_component ("Ra"),
-      babl_component ("Ga"),
-      babl_component ("Ba"),
+      babl_component ("R'a"),
+      babl_component ("G'a"),
+      babl_component ("B'a"),
       babl_component ("A"),
       NULL);
   Babl *rgbA8 = babl_format_new (
-      babl_model ("RaGaBaA"),
+      babl_model ("R'aG'aB'aA"),
       babl_type  ("u8"),
-      babl_component ("Ra"),
-      babl_component ("Ga"),
-      babl_component ("Ba"),
+      babl_component ("R'a"),
+      babl_component ("G'a"),
+      babl_component ("B'a"),
       babl_component ("A"),
       NULL);
   Babl *rgbF = babl_format_new (
-      babl_model ("RGB"),
+      babl_model ("R'G'B'"),
       babl_type  ("float"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       NULL);
   Babl *rgb16 = babl_format_new (
-      babl_model ("RGB"),
+      babl_model ("R'G'B'"),
       babl_type  ("u16"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       NULL);
   Babl *rgb8 = babl_format_new (
-      babl_model ("RGB"),
+      babl_model ("R'G'B'"),
       babl_type  ("u8"),
-      babl_component ("R"),
-      babl_component ("G"),
-      babl_component ("B"),
+      babl_component ("R'"),
+      babl_component ("G'"),
+      babl_component ("B'"),
       NULL);
   Babl *gaF = babl_format_new (
-      babl_model ("YA"),
+      babl_model ("Y'A"),
       babl_type  ("float"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       babl_component ("A"),
       NULL);
   Babl *gAF = babl_format_new (
-      babl_model ("YaA"),
+      babl_model ("Y'aA"),
       babl_type  ("float"),
-      babl_component ("Ya"),
+      babl_component ("Y'a"),
       babl_component ("A"),
       NULL);
   Babl *gF = babl_format_new (
-      babl_model ("Y"),
+      babl_model ("Y'"),
       babl_type  ("float"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       NULL);
   Babl *ga16 = babl_format_new (
-      babl_model ("YA"),
+      babl_model ("Y'A"),
       babl_type  ("u16"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       babl_component ("A"),
       NULL);
   Babl *gA16 = babl_format_new (
-      babl_model ("YaA"),
+      babl_model ("Y'aA"),
       babl_type  ("u16"),
-      babl_component ("Ya"),
+      babl_component ("Y'a"),
       babl_component ("A"),
       NULL);
   Babl *g16 = babl_format_new (
-      babl_model ("Y"),
+      babl_model ("Y'"),
       babl_type  ("u16"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       NULL);
   Babl *ga8 = babl_format_new (
-      babl_model ("YA"),
+      babl_model ("Y'A"),
       babl_type  ("u8"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       babl_component ("A"),
       NULL);
   Babl *gA8 = babl_format_new (
-      babl_model ("YaA"),
+      babl_model ("Y'aA"),
       babl_type  ("u8"),
-      babl_component ("Ya"),
+      babl_component ("Y'a"),
       babl_component ("A"),
       NULL);
   Babl *g8 = babl_format_new (
-      babl_model ("Y"),
+      babl_model ("Y'"),
       babl_type  ("u8"),
-      babl_component ("Y"),
+      babl_component ("Y'"),
       NULL);
   Babl *yuv8 = babl_format_new (
       "name", "Y'CbCr u8",
@@ -1937,6 +2006,8 @@ init (void)
   o (rgbF, yuvF);
   o (yuvaF, rgbaF);
   o (rgbaF, yuvaF);
+  o (rgbaF, rgbaD);
+  o (rgbaD, rgbaF);
 #if 0
   o (rgbF, xyzF);
   o (xyzF, rgbF);
-- 
2.30.2